package traversals;

import tester.Tester;
import tester.Traversal;

/**
 * <P>The tester recognizes an additional interface
 * <CODE>{@link tester.Traversal Traversal}</CODE>. This is a
 * functional iterator that provides methods for traversing
 * over the elements of a data structure.</P>
 *
 * <P>If the user implements the
 * <CODE>{@link tester.Traversal Traversal}</CODE> interface for
 * his/her own class, the
 * <CODE>{@link tester.Tester#checkExpect checkExpect}</CODE>
 * still examines the data within the class by comparing the
 * values of the corresponding fields. To invoke the comparison
 * of the data generated by the <CODE>Traversal</CODE> iterator,
 * the user needs to use the
 * <CODE>{@link tester.Tester#checkTraversal checkTraversal}</CODE>
 * (or the inexact variant, the
 * <CODE>{@link tester.Tester#checkInexactTraversal checkInexactTraversal}</CODE>)
 * method.</P>
 * 
 * @author Virag Shah
 * @since 25 February 2011
 * 
 */
public class ExamplesTraversals {
	/**
	 * Sample data: <CODE>{@link Song Song}</CODE> -- a class used in lists,
	 * <CODE>{@link Traversal Traversal}</CODE>Traversal,
	 * <code>ArrayList</code examples
	 */
	public Song song1 = new Song("title1", 4);
	public Song song2 = new Song("title2", 2);
	public Song song3 = new Song("title3", 3);
	public Song song1a = new Song("title1", 4);   // equivalent to song1

	/** Sample lists of data */
	/**
	 * Sample data: A <CODE>{@link Traversal Traversal}</CODE> over
	 * a list of <CODE>{@link Song Song}</CODE>
	 */
	public Traversal<Song> songlistTr1 = new ConsListTr<Song>(
			song1,                            // the first element in the list
			new ConsListTr<Song>(
					song2,                    // the second element in the list
					new ConsListTr<Song>(
							song3,            // the third element in the list
							new MTListTr<Song>())));  // empty list

	/**
	 * Sample data: A <CODE>{@link Traversal Traversal}</CODE> over
	 * a list of <CODE>{@link Song Song}</CODE> with the same data
	 */
	public Traversal<Song> songlistTr2 = new ConsListTr<Song>(
			song1,                            // the first element in the list
			new ConsListTr<Song>(
					song2,                    // the second element in the list
					new ConsListTr<Song>(
							song3,            // the third element in the list
							new MTListTr<Song>())));  // empty list

	/**
	 * Sample data: A <CODE>{@link Traversal Traversal}</CODE> over
	 * a list of <CODE>{@link Song Song}</CODE> with different
	 * instance of the same data
	 */
	public Traversal<Song> songlistTr1a = new ConsListTr<Song>(
			song1a,                           // the first element in the list
			new ConsListTr<Song>(
					song2,                    // the second element in the list
					new ConsListTr<Song>(
							song3,            // the third element in the list
							new MTListTr<Song>())));  // empty list

	/**
	 * Sample data: A <CODE>{@link Traversal Traversal}</CODE> over
	 * a shorter list of <CODE>{@link Song Song}</CODE>
	 */
	public Traversal<Song> songlistTr3 = new ConsListTr<Song>(
			song1,                            // the first element in the list
			new ConsListTr<Song>(
					song2,                    // the second element in the list
					new MTListTr<Song>()));      // empty list

	/**
	 * Sample data: A <CODE>{@link Traversal Traversal}</CODE> over
	 * a list of <CODE>{@link Song Song}</CODE> with different data
	 */
	public Traversal<Song> songlistTr4 = new ConsListTr<Song>(
			song1,                            // the first element in the list
			new ConsListTr<Song>(
					song3,                    // the second element in the list
					new ConsListTr<Song>(
							song2,            // the third element in the list
							new MTListTr<Song>())));  // empty list

	/**
	 * Test the comparison of Array data.
	 * All the tests provided here compare equivalent instances of
	 * <CODE>{@link AListTr}</CODE> comprising instances of
	 * <CODE>{@link Song}</CODE> class. All the tests should succeed.
	 *
	 * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
	 */
	public void testArraysSucceed(Tester t) {

		t.checkExpect(
				songlistTr2,  // object 1
				songlistTr1,  // object 2
		"Success: same Traversal-s of songs - shown as lists");  // test case name

		t.checkTraversal(
				songlistTr2,  // object 1
				songlistTr1,  // object 2
		"Success: same Traversal-s of songs - shown as Traversal-s"); // test case name

		t.checkTraversal(
				songlistTr1a, // object 1
				songlistTr1,  // object 2
		"Success: same Traversal-s of songs (different instance of the same data) - shown as Traversal-s"); // test case name
	}

	/**
	 * Test the comparison of Array data.
	 * All the tests provided here compare non-equivalent instances of
	 * <CODE>{@link AListTr}</CODE> comprising instances of
	 * <CODE>{@link Song}</CODE> class. All the tests should fail.
	 *
	 * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
	 */
	public void testArraysFail(Tester t) {
		t.checkTraversal(
				songlistTr3,  // object 1 (2 elements in the list)
				songlistTr1,  // object 2 (3 elements in the list)
		"Should fail: different Traversal-s of songs - first list is shorter"); // test case name

		t.checkTraversal(
				songlistTr1,  // object 1 (3 elements in the list)
				songlistTr3,  // object 2 (2 elements in the list)
		"Should fail: different Traversal-s of songs - second list is shorter"); // test case name

		t.checkTraversal(
				songlistTr1,  // object 1
				songlistTr4,  // object 2
		"Should fail: different Traversal-s of songs - different order of data"); // test case name
	}

	/**
	 * Test the comparison of <CODE>{@link BinarySearchTreeTr Binary Search Trees}</CODE>.
	 * Here we compare two binary search trees that are equivalent in terms of their
	 * <I>inorder</I>.
	 *
	 * Testing equivalence with
	 * <CODE>{@link tester.Tester#checkTraversal checkTraversal}</CODE>
	 * should succeed, unlike doing it with
	 * <CODE>{@link tester.Tester#checkExpect checkExpect}</CODE>.
	 *
	 * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
	 */
	public void testBinarySearchTrees(Tester t) {
		//  constructing tree1:
		//
		//            7
		//          /   \
		//         4     9
		//        / \   / \
		//       *   * *   *
		//
		Traversal<Integer> binarySearchTreeTr1 = new BinarySearchTreeTr<Integer>(
				new BinarySearchTreeTr<Integer>(4),    // left branch
				7,                                     // root node
				new BinarySearchTreeTr<Integer>(9));   // right branch

		//  constructing tree2:
		//
		//           4
		//         /   \
		//        *     9
		//             / \
		//            7   *
		//           / \
		//          *   *
		//
		Traversal<Integer> binarySearchTreeTr2 = new BinarySearchTreeTr<Integer>(
				new BinarySearchTreeTr<Integer>(),          // left branch is empty
				4,                                          // root node
				new BinarySearchTreeTr<Integer>(
						new BinarySearchTreeTr<Integer>(7),       // left branch
						9,                                        // node
						new BinarySearchTreeTr<Integer>()));      // right branch is empty


		t.checkTraversal(
				binarySearchTreeTr1,    // object 1
				binarySearchTreeTr2,    // object 2
		"Success: same Traversal-s of binary search tree - shown as Traversal-s");  // test case name

		t.checkExpect(
				binarySearchTreeTr1,   // object 1
				binarySearchTreeTr2,   // object 2
		"Should fail: same Traversal-s of binary search tree - checkExpect doesn't work");  // test case name
	}

	/**
	 * Sample data: A <CODE>{@link Traversal Traversal}</CODE> over
	 * a list of <CODE>Double</CODE>.
	 */
	public Traversal<Double> doubleListTr1 = new ConsListTr<Double>(
			1.0,                                    // the first element in the list
			new ConsListTr<Double>(
					10.0,                           // the second element in the list
					new ConsListTr<Double>(
							100.0,                  // the third element in the list
							new MTListTr<Double>())));  // empty list
	/**
	 * Sample data: A <CODE>{@link Traversal Traversal}</CODE> over
	 * a list of <CODE>Double</CODE>.
	 */
	public Traversal<Double> doubleListTr2 = new ConsListTr<Double>(
			1.0,                                    // the first element in the list
			new ConsListTr<Double>(
					10.0,                           // the second element in the list
					new ConsListTr<Double>(
							99.5,                   // the third element in the list
							// (slightly different from previous list)
							new MTListTr<Double>())));  // empty list

	/**
	 * Test the inexact comparison of Array data.
	 * All the tests provided here compare not exactly equivalent instances of
	 * <CODE>{@link AListTr}</CODE> comprising instances of
	 * <CODE>Double</CODE> class.
	 *
	 * Testing equivalence with  methods
	 * <CODE>{@link tester.Tester#checkExpect checkExpect}</CODE> and
	 * <CODE>{@link tester.Tester#checkTraversal checkTraversal}</CODE>
	 * will fail. Invoking the method
	 * <CODE>{@link tester.Tester#checkInexactTraversal checkInexactTraversal}</CODE>
	 * and setting the <CODE>tolerance</CODE> too tight will result in failure.
	 * By making <CODE>tolerance</CODE> loose enough we will succeed eventually.
	 *
	 * @param t the <CODE>{@link Tester Tester}</CODE> that performs the tests
	 */
	public void testCheckInexactTraversal(Tester t) {

		t.checkExpect(
				doubleListTr1,  // object 1
				doubleListTr2,  // object 2
		"Should fail: not exactly equivalent Traversal-s of Double - shown as lists"); // test case name

		t.checkTraversal(
				doubleListTr1,  // object 1
				doubleListTr2,  // object 2
		"Should fail: not exactly equivalent Traversal-s of Double - shown as Traversal-s"); // test case name

		t.checkInexactTraversal(
				doubleListTr1,  // object 1
				doubleListTr2,  // object 2
				0.001,          // tolerance level (too tight)
		"Should fail: not exactly equivalent Traversal-s of Double - the tolerance is too tight"); // test case name

		t.checkInexactTraversal(
				doubleListTr1,  // object 1
				doubleListTr2,  // object 2
				0.01,           // tolerance level (loose enough)
		"Success: not exactly equivalent Traversal-s of Double - the tolerance is loose enough"); // test case name

	}

	/**
	 * <P>Display all data defined in the <CODE>{@link ExamplesTraversals ExamplesTraversals}</CODE> 
	 * class.</P>
	 * <P>Run all tests defined in the <CODE>{@link ExamplesTraversals ExamplesTraversals}</CODE> 
	 * class.</P>
	 */
	public static void main(String[] argv) {
		ExamplesTraversals et = new ExamplesTraversals();

		System.out.println("Show all data defined in the ExamplesTraversals class:");
		System.out.println("\n\n---------------------------------------------------");
		System.out.println("Invoke tester.runReport(this, true, true):");
		System.out.println("Print all data, all test results");

		Tester.runReport(et, true, true);

		System.out.println("\n---------------------------------------------------");
		System.out.println("\n---------------------------------------------------");
		System.out.println("\n---------------------------------------------------");
		System.out.println("Invoke tester.runReport(this, false, false, true):");
		System.out.println("Print no data, all test results, no warnings");

		Tester.runReport(et, false, false);
	}
}